package br.com.roteador.endereco;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.apache.commons.beanutils.BeanUtils;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.view.Results;
import br.com.roteador.component.AcessSession;
import br.com.roteador.component.GeoLocationComponent;
import br.com.roteador.component.StringUteis;
import br.com.roteador.controller.BasicController;
import br.com.roteador.rota.Destino;

@Controller
public class EnderecoController extends BasicController {
	@Inject private EnderecoDAO enderecoDAO;

	public EnderecoController(Result result, ResourceBundle bundle,
			EnderecoDAO enderecoDAO, AcessSession session) {
		this.result = result;
		this.bundle = bundle;
		this.enderecoDAO = enderecoDAO;
		this.session = session;
	}
    
    public EnderecoController(){}
    
    @PostConstruct
    private void init(){
    	injetaUsuario();
    }
    
    @Path(value = "/" + ENDERECO )
    public void endereco(){
    	List<Endereco> lista = enderecoDAO.recuperaEnderecos();
    	for(Endereco end : lista){
    		end.getDestinos();
    	}
    	result.include("listaEnderecos", lista);
    }
    
    @Path(value = "/" + ENDERECO + "/" + NOVO)
    public void novo(){
    	result.include("endereco", new Endereco());
    }
    
    @Path(value = "/" + ENDERECO + "/recuperaEnderecos")
    public void recuperaEnderecos(){
    	result.use(Results.json()).from(enderecoDAO.recuperaEnderecos()).serialize();
    }
    
    @Path(value = "/" + ENDERECO + "/" + EXCLUIR)
    @Post
    public void excluir(String id){
    	if(!StringUteis.isEmpty(id)){
    		Endereco endereco = (Endereco) enderecoDAO.find(Endereco.class, Integer.parseInt(id));
    		endereco.getDestinos();
    		if(endereco != null && endereco.getDestinos().size() > 0){
    			mensagemErro("erro.endereco.nao.pode.excluir");
    		} else {
    			enderecoDAO.remove(endereco);
            	mensagemSucesso("endereco.excluido.sucesso");
    		}
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    	redirect();
    }
    
    @Path(value = "/" + ENDERECO + "/" + EDITAR)
    public void editar(String id){
    	if(!StringUteis.isEmpty(id)){
    		Endereco endereco = (Endereco) enderecoDAO.find(Endereco.class, Integer.parseInt(id));
	        result.include(ENDERECO, endereco);
    	} else {
    		mensagemErro("erro.ao.recuperar");
    	}
    }

	@Override
	protected void redirect() {
		 result.redirectTo(EnderecoController.class).endereco();
	}

	@Path(value = "/" + ENDERECO + "/" + GRAVAR)
    @Post
	public void gravar(Endereco endereco) {
		if(endereco != null){
			if(StringUteis.isEmpty(endereco.getDescricao())){
    			mensagemErro("erro.descricao.endereco.obrigatorio");
    		}
    		if(StringUteis.isEmpty(endereco.getCep())){
    			mensagemErro("erro.cep.endereco.obrigatorio");
    		}
    		if(StringUteis.isEmpty(endereco.getNumero())){
    			mensagemErro("erro.numero.endereco.obrigatorio");
    		}
    		if(resultPossui(ERROR) && resultPossuiConteudo(ERROR)){ redirect(); return;}
	        
	        if(endereco.getId() != null){
	        	editar(endereco);
	        } else {
	        	Endereco pre = enderecoDAO.recuperaEnderecoPorCEPNumero(endereco.getCep(), endereco.getNumero());
	    		if(pre != null){//Mesmo endereço
	    			mensagemErro("erro.endereco.existe");
	    		} else {
	    			recuperaLatLon(endereco);
		        	endereco.setUsuario(session.getUsuario());
		        	endereco.setDataGravacao(new Date());
		        	enderecoDAO.save(endereco);
		            mensagemSucesso("endereco.gravado.sucesso");
	    		}
	        }
    	} else {
    		mensagemErro("erro.ao.gravar");
    	}
        redirect();
	}
	
	private void recuperaLatLon(Endereco endereco){
		String code = endereco.getCep() + " " + endereco.getLogradouro() + " " + endereco.getNumero() + " " 
        		+ endereco.getBairro() + " " + endereco.getCidade() + " " + endereco.getEstado();
        String response = GeoLocationComponent.getLocation(code);
        String[] result = GeoLocationComponent.parseLocation(response);
        endereco.setLatitude(result[0]);
        endereco.setLongitude(result[1]);
	}
	
	private void editar(Endereco endereco) {
		Endereco pre = enderecoDAO.recuperaEnderecoPorCEPNumero(endereco.getCep(), endereco.getNumero());
		if(pre != null && pre.getId() != endereco.getId()){//Mesmo endereço com ids diferentes
			mensagemErro("erro.endereco.existe");
		} else {
			Date data = pre.getDataGravacao();
			List<Destino> destinos = pre.getDestinos();
			try {
                BeanUtils.copyProperties(pre, endereco);
            } catch (IllegalAccessException e) {
            	mensagemErro("erro.ao.gravar");
            } catch (InvocationTargetException e) {
            	mensagemErro("erro.ao.gravar");
            }
			recuperaLatLon(pre);
			pre.setDestinos(destinos);
			pre.setUsuario(session.getUsuario());
			pre.setDataGravacao(data);
			enderecoDAO.update(pre);
		}
	}

}